iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0
IT 管理

30 天玩轉 GAS: 打造你的個人自動化助手系列 第 29

[Day 29] GAS - 什麼!還能架網頁!來動手做 To-Do List

  • 分享至 

  • xImage
  •  

鐵人賽已經倒數兩天了!最後想教教大家一個有趣且進階的應用,就是部署靜態網頁!
大家相信下面這張網頁圖是用 GAS + google sheet 架出來的嗎~~

https://ithelp.ithome.com.tw/upload/images/20241009/201376802sgYRqulIv.png
讓我們一步一步拆解 GAS 部署網頁的過程吧!

GAS 部署網頁很難嗎?不會,超簡單

讓我們先用一個最簡單的 hello world 按鈕作為範例~

步驟 1:新增程式碼

GAS 架網頁只需要兩個元素:

  1. 前端 HTML
  2. Apps Script 後端程式碼

HTML 範例
按左上檔案的加號,建立一個名為 index 的 html 檔案

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <h1>Hello, World!</h1>
    <p>用 Google Apps Script 部署網頁好簡單~</p>
  </body>
</html>

Apps Script 後端程式碼
建立一個 gs 檔案,輸入以下程式碼:

function doGet() {
  // 載入並返回 HTML 頁面
  return HtmlService.createHtmlOutputFromFile('index'); // index 為網頁 html 名稱
}

步驟 2:部署為網頁應用程式

  1. 在 Google Apps Script 編輯器中,點擊「部署」>「新增部署作業」。
  2. 在「選擇部署類型」中,選擇「網頁應用程式」。
  3. 填寫專案名稱,並設置「具備存取權的使用者」:
    • 若只想讓自己訪問,選擇「僅限本人」。
    • 若要讓他人也能訪問,選擇「任何人」或「任何人(即使未登入)」。
  4. 點擊「部署」後,你會得到一個應用程式的 URL,複製 URL 到網址列,即可查看你剛部署的網頁!

Note:GAS 網頁部署跟 github 有點類似,並不會每分每秒立馬同步程式碼
如果有修改程式碼,需要即時看其所造成的網頁效果,可點擊「測試部署作業」> 複製「網頁應用程式」的網址連結至網址列,重新整理此連結便可瀏覽最新修改情形!

完成!!!

沒錯,這樣你就能獲得一個超簡樸的 Hello World 網頁~
https://ithelp.ithome.com.tw/upload/images/20241008/20137680MlufmmIIxf.png

但這樣太無聊~竟然都連結 Google Sheet 了
我們就來用 Google sheet 儲存資料,利用 GAS 來做CRUD 並幫我們呈現成網頁吧!


重頭戲!!用 GAS 實作 To-Do List 網頁

Purpose:

  • 可以同時用網頁和 Google Sheet 來管理資料(CRUD)

Feature:

  • 使用者可以在網頁上新增任務,並設立到期日。
  • 任務會被保存到 Google Sheets 中,並會自動紀錄創建日。
  • 網頁上會動態顯示任務列表,並可以刪除任務。
    你可以在 To-do List 中新增「到期日」和「創建日」欄位,並且讓「創建日」自動填入系統當前的日期和時間。以下是修改過的程式碼:

步驟 1:建立 Google Sheets 並新增欄位

  1. 開啟一個 Google Sheets ,並新增兩個新欄位:
    • A1: Task (任務)
    • B1: Due Date(截止日期)
    • C1: Creation Date(新增日期)

你的 Google Sheets 應該如下:

Task Due Date Creation Date
Task 1 2024-10-10 2024-10-03

步驟 2:開啟 GAS 並新增 HTML 前端程式碼

按左上角檔案的「+」號,新增一個 HTML 檔案,命名為 index,並輸入以下程式碼:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>
    <h1>To-Do List</h1>
    <input type="text" id="taskInput" placeholder="輸入任務">
    <input type="date" id="dueDateInput" placeholder="到期日">
    <button onclick="addTask()">新增任務</button>

    <table id="taskTable">
        <thead>
            <tr>
                <th>任務</th>
                <th>截止日期</th>
                <th>新增日期</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody id="taskBody">
            <!-- 任務清單會被 JavaScript 動態新增到這裡 -->
        </tbody>
    </table>
    <script>
      
      function loadTasks() {
          google.script.run.withSuccessHandler(function(tasks) {
              var taskTable = document.getElementById('taskTable');
              var taskBody = document.getElementById('taskBody');
              taskBody.innerHTML = '';  // 清空表格內容
              
              if (tasks.length > 0) {
                  tasks.forEach(function(task) {
                      var row = document.createElement('tr'); 
                      var taskCell = document.createElement('td'); // 任務單元格
                      var dueDateCell = document.createElement('td'); // 截止日期單元格
                      var creationDateCell = document.createElement('td'); // 新增日期單元格
                      var deleteCell = document.createElement('td'); // 刪除按鈕單元格
                      
                      taskCell.textContent = task.task; // 設定任務內容
                      dueDateCell.textContent = task.dueDate; // 設定截止日期
                      creationDateCell.textContent = task.creationDate; // 設定新增日期
                      
                      // 創建刪除按鈕
                      var deleteBtn = document.createElement('button');
                      deleteBtn.textContent = '刪除';
                      deleteBtn.className = 'delete-btn';
                      deleteBtn.onclick = function() {
                          deleteTask(task.task);
                      };
                      
                      deleteCell.appendChild(deleteBtn); // 將刪除按鈕新增到單元格
                      row.appendChild(taskCell); // 將任務單元格新增到行
                      row.appendChild(dueDateCell); // 將截止日期單元格新增到行
                      row.appendChild(creationDateCell); // 將新增日期單元格新增到行
                      row.appendChild(deleteCell); // 將刪除按鈕單元格新增到行
                      
                      taskBody.appendChild(row); // 將整行新增到表格主體中
                  });
              } else {
                  console.log('沒有找到任務');
              }
          }).getTasks();  // 呼叫 GAS 後端函數取得任務
      }

      // 新增任務
      function addTask() {
        var task = document.getElementById('taskInput').value;
        var dueDate = document.getElementById('dueDateInput').value;
        if (task && dueDate) {
          google.script.run.withSuccessHandler(loadTasks).addTask(task, dueDate);  // 新增後重新載入任務列表
          document.getElementById('taskInput').value = '';  // 清空輸入框
          document.getElementById('dueDateInput').value = '';  // 清空日期框
        } else {
          alert('請輸入任務和截止日期');
        }
      }

      // 刪除任務
      function deleteTask(task) {
        google.script.run.withSuccessHandler(loadTasks).deleteTask(task);  // 刪除後重新載入任務列表
      }

      // 當頁面載入完成後,自動載入任務
      window.onload = loadTasks;
    </script>
  </body>
</html>
  • 我們建立了 input 欄位,讓使用者可以輸入 task 和 Due Date。當使用者點擊「新增任務」按鈕時,會執行 js addTask 的 function,google.script.run.withSuccessHandler(loadTasks).addTask(task, dueDate); 意思是會等後端 GAS addTask() 成功後,再執行 js loadTask 的 function.

步驟 3:修改 Google Apps Script 後端程式碼

// 取得 Google 試算表
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('{你的工作表名稱}');;

// 返回 HTML 頁面
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index');
}

// 從 Google Sheets 中取得所有任務
function getTasks() {
  var data = sheet.getRange(2, 1, sheet.getLastRow() - 1, 3).getValues();  // 讀取所有行的三列數據
  var tasks = [];
  for (var i = 0; i < data.length; i++) {
    var row = data[i];
    tasks.push({
      task: row[0],
      dueDate: row[1].toISOString().split('T')[0],
      creationDate: row[2].toISOString().split('T')[0]
    });
  }
  return tasks;
}

// 新增任務,並包含到期日與創建日
function addTask(task, dueDate) {
  var creationDate = new Date();  // 自動生成新增日期
  sheet.appendRow([task, dueDate, creationDate]);  // 將新任務、截止日期和新增日期寫入試算表
}

// 刪除任務
function deleteTask(task) {
  var range = sheet.getDataRange();  // 取得所有資料範圍
  var values = range.getValues();
  for (var i = 1; i < values.length; i++) {
    if (values[i][0] == task) {
      sheet.deleteRow(i + 1);  // 刪除對應列
      break;
    }
  }
}
  • getTasks 取得所有任務資料,注意!從 google sheet 讀取回來的資料格式為 Date Obj, 需把它轉型為 string 再傳回前端顯示!
  • addTask() 接收來自前端資料,並將其儲存到 Google 試算表中。
  • deleteTask() 接收來自前端的命令,並這列資料從 Google 試算表中刪除。

步驟 4:部署網頁應用程式

  1. 在 Google Apps Script 編輯器中,點擊「部署」>「新增部署作業」。
  2. 選擇「網頁應用程式」作為部署類型。
  3. 設置應用程式名稱,並選擇「任何人」為存取權限,這樣所有人都可以訪問該網頁應用程式。
  4. 部署後會生成一個 URL,這個 URL 就是你的 To-do List 網頁應用程式。

查看網頁就會得到像這樣的畫面:
https://ithelp.ithome.com.tw/upload/images/20241009/20137680VrpA1VxcZr.png

建立幾個簡單的任務清單後的畫面:
https://ithelp.ithome.com.tw/upload/images/20241009/20137680ZcRqhP4OOV.png

步驟 5:美化網頁

目前只有單純的 html,顯示起來相對單調,讓我們加入一些 css 語法讓他變得好看吧!
更新 html 檔:

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
        body {
            font-family: Arial, sans-serif;
            background-color: #f4f4f4;
            margin: 20px;
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        }

        th, td {
            padding: 12px;
            text-align: left;
            border: 1px solid #ddd;
        }

        th {
            background-color: #4CAF50; /* 標題行顏色 */
            color: white;
        }

        tr:nth-child(even) {
            background-color: #f2f2f2; /* 偶數行顏色 */
        }

        tr:hover {
            background-color: #ddd; /* 滑鼠懸停效果 */
        }

        caption {
            margin: 10px;
            font-size: 1.5em;
            font-weight: bold;
            color: #333;
        }
    </style>
  </head>
  <body>
    <h1>To-Do List</h1>
    <input type="text" id="taskInput" placeholder="輸入任務">
    <input type="date" id="dueDateInput" placeholder="到期日">
    <button onclick="addTask()">新增任務</button>

    <table id="taskTable">
        <thead>
            <tr>
                <th>任務</th>
                <th>截止日期</th>
                <th>新增日期</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody id="taskBody">
            <!-- 任務清單會被 JavaScript 動態新增到這裡 -->
        </tbody>
    </table>
    <script>
      
      function loadTasks() {
          google.script.run.withSuccessHandler(function(tasks) {
              var taskTable = document.getElementById('taskTable');
              var taskBody = document.getElementById('taskBody');
              taskBody.innerHTML = '';  // 清空表格內容
              
              if (tasks.length > 0) {
                  tasks.forEach(function(task) {
                      var row = document.createElement('tr'); 
                      var taskCell = document.createElement('td'); // 任務單元格
                      var dueDateCell = document.createElement('td'); // 截止日期單元格
                      var creationDateCell = document.createElement('td'); // 新增日期單元格
                      var deleteCell = document.createElement('td'); // 刪除按鈕單元格
                      
                      taskCell.textContent = task.task; // 設定任務內容
                      dueDateCell.textContent = task.dueDate; // 設定截止日期
                      creationDateCell.textContent = task.creationDate; // 設定新增日期
                      
                      // 創建刪除按鈕
                      var deleteBtn = document.createElement('button');
                      deleteBtn.textContent = '刪除';
                      deleteBtn.className = 'delete-btn';
                      deleteBtn.onclick = function() {
                          deleteTask(task.task);
                      };
                      
                      deleteCell.appendChild(deleteBtn); // 將刪除按鈕新增到單元格
                      row.appendChild(taskCell); // 將任務單元格新增到行
                      row.appendChild(dueDateCell); // 將截止日期單元格新增到行
                      row.appendChild(creationDateCell); // 將新增日期單元格新增到行
                      row.appendChild(deleteCell); // 將刪除按鈕單元格新增到行
                      
                      taskBody.appendChild(row); // 將整行新增到表格主體中
                  });
              } else {
                  console.log('沒有找到任務');
              }
          }).getTasks();  // 呼叫 GAS 後端函數取得任務
      }

      // 新增任務
      function addTask() {
        var task = document.getElementById('taskInput').value;
        var dueDate = document.getElementById('dueDateInput').value;
        if (task && dueDate) {
          google.script.run.withSuccessHandler(loadTasks).addTask(task, dueDate);  // 新增後重新載入任務列表
          document.getElementById('taskInput').value = '';  // 清空輸入框
          document.getElementById('dueDateInput').value = '';  // 清空日期框
        } else {
          alert('請輸入任務和截止日期');
        }
      }

      // 刪除任務
      function deleteTask(task) {
        google.script.run.withSuccessHandler(loadTasks).deleteTask(task);  // 刪除後重新載入任務列表
      }

      // 當頁面載入完成後,自動載入任務
      window.onload = loadTasks;
    </script>
  </body>
</html>

Note: GAS 並不是專門為了網頁所設計,所以只能支援最單純的 css 語法,且只能加入至 html 檔案當中,沒辦法另外建立 css file 唷~

Result

網頁呈現:
https://ithelp.ithome.com.tw/upload/images/20241009/20137680hFDDUScwhk.png

而背後 Google Sheet 的資料對應如下:

https://ithelp.ithome.com.tw/upload/images/20241009/20137680M7A0GsqDGu.png

這樣就建立好一個 To-Do List 的網頁啦 🚀🚀🚀
你可以透過網頁做增刪改減,也可以透過 google sheet 管理資料!
如此你就學會如何用 GAS 部署網站啦~
快依照這個範例做出類似的應用,漂亮的顯示你想呈現的資料吧!


上一篇
[Day 28] GAS - 什麼!還能夠傳賴?自動化發送通知到 LINE
下一篇
[Day 30] GAS 最終回 - 總回顧、限制、資源,下一步該怎麼走
系列文
30 天玩轉 GAS: 打造你的個人自動化助手30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言